﻿using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using FluentAssertions;
using KvDb.Tests;
using KvDb.Tests.SupportingTypes;
using KvDbApi;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace KvDb.IntegrationTests
{
    [TestClass]
    public class BufferedValueListTests
    {
        private static readonly byte[] data16K = BufferHelper.Data16K;

        [TestCategory("SQL Server Integrated Test")]
        [TestMethod]
        public void BufferedValueListSmallArrayCanBeSavedUsingKvSet()
        {
            var handle = new ValueHandle("testKey" + Guid.NewGuid().ToString());
            using (var c = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlKvDb"].ConnectionString))
            {
                var data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
                var buffer = new BufferedValueCollection(data);

                SqlParameter versionOutput;
                SqlParameter expiryOutput;
                using (var setCommand = c.CreateKvSet(handle, buffer, out versionOutput, out expiryOutput))
                {
                    setCommand.ExecuteNonQuery();
                }

                ((int)versionOutput.Value).Should().BeGreaterThan(Usage.ValueNotFound);

                using (var getCommand = c.CreateKvGet(handle, true, out versionOutput, out expiryOutput))
                {
                    using (var r = getCommand.ExecuteReader())
                    {
                        r.Read().Should().BeTrue();

                        var result = new byte[10];
                        r.GetBytes(1, 0, result, 0, 10);

                        BufferHelper.CompareBuffers(data, 0, result, 0, 10);
                    }

                    ((int)versionOutput.Value).Should().Be(((int)versionOutput.Value));
                }
            }
        }

        [TestCategory("SQL Server Integrated Test")]
        [TestMethod]
        public void BufferedValueListBigArrayCanBeSavedHardenedAndRetrieved()
        {
            var handle = new ValueHandle("testKeyHarden:" + Guid.NewGuid().ToString());
            handle.TimeToLive = TimeSpan.FromMilliseconds(1);

            using (var c = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlKvDb"].ConnectionString))
            {
                var buffer = new BufferedValueCollection(data16K);

                SqlParameter versionOutput;
                SqlParameter expiryOutput;
                using (var setCommand = c.CreateKvSet(handle, buffer, out versionOutput, out expiryOutput))
                {
                    setCommand.ExecuteNonQuery();
                }

                ((int)versionOutput.Value).Should().BeGreaterThan(Usage.ValueNotFound);

                Thread.Sleep(5);

                using (var hardenCommand = c.CreateCommand())
                {
                    hardenCommand.CommandText = "store.kvHarden";
                    hardenCommand.CommandType = CommandType.StoredProcedure;
                    hardenCommand.ExecuteNonQuery();
                }

                SqlParameter getVersionOutput;
                SqlParameter getExpiryOutput;
                using (var kvGet = c.CreateKvGet(handle, false, out getVersionOutput, out getExpiryOutput))
                {
                    using (var r = kvGet.ExecuteReader())
                    {
                        var sourceOffset = 0;
                        var resultBuffer = new byte[Usage.ValuePartSize];
                        while (r.Read())
                        {
                            var size = r.GetInt32(0);
                            r.GetBytes(1, 0, resultBuffer, 0, size);
                            BufferHelper.CompareBuffers(resultBuffer, 0, data16K, sourceOffset, size);
                            sourceOffset += size;
                        }
                    }
                }
            }
        }
    }
}
